Maxiee 的 Emacs 之旅:RSS 阅读器
介绍
Elfeed 是一个轻量且强大的 Emacs RSS 阅读器。有多强大呢?它能自动根据内容给 feed 打标签。除此之外,结合 elisp 和函数式编程,Elfeed 更像是一个 SDK,各个环节都可以进行定制,没有做不到,只有想不到。
为什么要在 Emacs 里使用 RSS 阅读器?
- Just for fun 😄
- 强大的二次开发能力
- 我的书签系统也是基于 org mode 可以打通
- 理想情况:需要 mark 的文章,直接 refile 到 bookmark 中
- 上班摸 🐟 不露痕迹 👀
二次开发能力值得一提,大多数产品都不具备开放性,开发者、产品经理设计成啥样就是啥样。但是,众口难调,每个人都有特殊的偏好。因此,只有开放性的产品才能满足对品质有要求的用户。如何提供开放性呢?有的产品提供 Plugin 插件机制,基于有限的 API 进行扩展。这种对 API 进行定制的能力,基于 OOP 语言是比较困难的。elisp + 函数式编程实现了完全定制能力,这是乐趣所在。
安装
我使用 Doom Emacs。Doom Emacs 中已经集成有 rss 模式。
进入 DOOMDIR/init.el 后,将 rss 对应项目解开注释即可。
(rss +org)
需要注意的是,+org
会同时安装 elfeed-org 这个扩展。elfeed 默认使用 elisp 管理 Feed,使用 elfeed-org 之后,改为使用 org 来管理 feed,更加方便。
关于 elfeed-org 的使用方式,会在后续小节中介绍。
本文后续的讲解也是基于 Doom Emacs,因为 Doom Emacs 对 elfeed 进行了二次定制,所以使用方式是与众不同的。
进入 elfeed
M-x elfeed
:
内容为空,因为还没有添加 Feed。
数据库
Elfeed 采用数据库来存储 Feed 数据。神奇的是这个数据库也是 Plain Text 的,因此我能够使用 Git 跟踪。
通过下面代码,修改数据库路径:
;; 指定 elfeed 数据库所在目录
(setq elfeed-db-directory "~/org/elfeed")
;; 指定 elfeed-org feed 源声明对应文件
(setq rmh-elfeed-org-files (list "~/org/elfeed.org"))
使用 elfeed-org 管理订阅源
如果使用 elfeed-org,则使用 org 文件管理订阅源,对应文件为 ~/org/elfeed.org,具体内容:
其中:
- 必须有一个跟节点,tag 必须为 elfeed,标题没要求
- 内部标题随便订
- 可以只插入一个 RSS Link
- 也可以按照 Org Link 方式,给一个规整的名字
- 标题可以插入 Tag,作为站点的 Tag 分类
- Tag 是可以继承的,比如
- 科技网站的 tag 是 tech
- MakeTechEasier 会自动继承 tech 的 tag
- Tag 是可以继承的,比如
刷新 Feed
回到 elfeed,执行 M-x elfeed-update
。可以看到 Feed 拉取下来了:
打开资讯
两种打开方式:
- Enter 应用内打开
- Shift + Enter:通过浏览器打开
应用内打开效果:
按 q 后返回。
不论是应用内打开,还是浏览器打开,在资讯列表页,可看到该条目已置灰,表示已读。
添加 Tag
对于好文章,可以添加 Tag 归类:
- 首先移动到文章所在行
- 输入加号
+
- 底部会弹出 Tag 输入框,输入对应 Tag 名称即可
按 Tag 过滤
输入 s,底部出现一个 Filter 输入框。
输入框默认值包括 @2-week-ago,这是 Elfeed 中的过滤语法,只展示两周内的文章。
在其后添加 tag 名称即可:
+tag
:表示正向条件,含该分类-tag
:表示负向条件,排除该分类- 不带加号:标题关键字搜索
- 条件间通过空格间隔,同时生效
其中,可以看到,tag 是包含正反过滤的,非常方便。
举例来说,假设 mark 标签表示好文章,read 标签表示已读。那么 +mark -read
表示未读好文章。
按时间过滤
Elfeed 中包含了一个强大的标签系统,除了按标签过滤外,还支持按照时间进行过滤:
- 最近六个月:@6-month-ago
- 最近两周:@2-week-ago
- 指定日期:@2020-06-19
- 指定时间段:@2020-06-19--2020-03-10
自动刷新 Feed
Elfeed 并没有提供自动刷新机制,通过自定义,实现了两种方式。修改 doom emacs 的 config.el:
启动 elfeed 时拉取 feed
;; Automatically updating feed when opening elfeed
(add-hook! 'elfeed-search-mode-hook #'elfeed-update)
使用定时器
;; Run `elfeed-update' every 24 hours
(run-at-time nil (* 24 60 60) #'elfeed-update)
基于 URL 自动打标签
TBD:以下是 elfeed 原生方法,增加 elfeed-org 的方法。
elfeed-new-entry-hook
在添加条目时候的钩子方法。
在钩子中使用 elfeed-make-tagger
函数进行打标签。实例代码:
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :feed-url "medium\\.com"
:add '(medium)))
这样,url 中带有 medium.com 的都会添加 medium 标签。 例2,只对 3 个月以前的文章打标签:
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :feed-url "medium\\.com"
:before "3 months ago"
:add 'medium))
例3,自动对 youtube 网站打标签:
;; Mark all YouTube entries
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :feed-url "youtube\\.com"
:add '(video youtube)))
例4,超过一定事前之前的,自动算作已读:
;; Entries older than 2 weeks are marked as read
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :before "2 weeks ago"
:remove 'unread))
钩子函数
除了 elfeed-new-entry-hook
之外,还有以下钩子:
hook | 功能 |
---|---|
elfeed-new-entry-hook | 添加新条目时调用 |
elfeed-new-entry-parse-hook | 添加新条目解析内容时调用 |
elfeed-http-error-hooks | 网络错误时调用 |
elfeed-parse-error-hooks | 解析错误时调用 |
elfeed-db-update-hook | 数据库主要修改更新时调用 |
展示条目
控制按下回车时的展示方式,通过 elfeed-show-mode
控制,默认是使用内置的 shr 包。
展示图片会导致 Emacs 变慢,可以设置 shr-inhibit-images
变量关闭图片展示。
elfeed-tube
除了订阅文章之外,通过 elfeed-tube 二次扩展,elfeed 还能够实现 Youtube 订阅。尤其地,还能与 youtube-dl 打通,实现视频下载。